#include "LPC11xx.h"
#include "bitops.h"
#include "spi.h"
#include "spiuart.h"
#include "delay.h"
#include <stdio.h>

#define RHR 0x00
#define THR 0x00
#define FCR 0x02
#define LCR 0x03
#define LSR 0x05

//when LCR bit 7 is set
#define DLL 0x00
#define DLH 0x01

uint8_t read_reg(uint8_t channel, uint8_t reg)
{
  uint8_t retval;
  //拉低片选（选择从设备进行通信）
  clrbit(LPC_GPIO2->DATA, 0);
  //发送寄存器地址
  spi1_send((1 << 7) | (reg << 3) | (channel << 1));
  //读取寄存器内容
  retval = spi1_recv();
  //拉高片选
  setbit(LPC_GPIO2->DATA, 0);
  
  return retval;
}

void write_reg(uint8_t channel, uint8_t reg, uint8_t data)
{
  //拉低片选
  clrbit(LPC_GPIO2->DATA, 0);
  //发送寄存器地址
  spi1_send((reg << 3) | (channel << 1));
  //读取寄存器内容
  spi1_send(data);
  //拉高片选
  setbit(LPC_GPIO2->DATA, 0);
}

void spiuart_init(int channel, int baudrate)
{
  //晶振频率为14745600Hz
  uint16_t div = 14745600/16/baudrate;
  
  //配置SPI引脚功能
  //作为主设备时SSEL1引脚需要配置为GPIO输出，默认高电平
  setbit(LPC_GPIO3->DATA, 0);
  setbit(LPC_GPIO2->DIR, 0);

  //配置扩展串口波特率9600，8N1
  write_reg(channel, LCR, 0x83);
  write_reg(channel, DLL, div & 0xff); 
  write_reg(channel, DLH, div >> 8);
  write_reg(channel, LCR, 0x03);
  
  //启用FIFO并清空
  write_reg(channel, FCR, 0x07);
}

//向串口发送一个字节
void spiuart_send_byte(int channel, uint8_t data)
{
  //等待发送保持寄存器为空
  while (!chkbit(read_reg(channel, LSR), 5));
  write_reg(channel, THR, data);
}

//从串口读取一个字节
//返回读取的字符，超时返回EOF
int spiuart_recv_byte(int channel, uint32_t timeout)
{
  uint8_t byte = 0;
  uint32_t begin = tick_count;
  //接收队列为空执行循环等待
  while (!chkbit(read_reg(channel, LSR), 0))
  {
    //超时
    if (tick_count - begin >= timeout)
    {
      return EOF;
    }
  }
  
  //从接收队列中读取数据
  byte = read_reg(channel, RHR);
  
  return byte;
}
